﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Serialization;
using Sunny.UI;

namespace DevelopTool.Common
{
    public static class JsonHelper
    {
        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <param name="settings"></param>
        /// <returns></returns>
        public static T DeserializeObject<T>(this string json, JsonSerializerSettings settings)
        {
            return JsonConvert.DeserializeObject<T>(json, settings);
        }

        /// <summary>
        /// 反序列化
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="json"></param>
        /// <returns></returns>
        public static T DeserializeObject<T>(this string json)
        {
            return JsonConvert.DeserializeObject<T>(json);
        }

        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="obj"></param>
        /// <param name="settings"></param>
        /// <returns></returns>
        public static string SerializeObject(this object obj, JsonSerializerSettings settings = null)
        {
            // 设置 Json 序列化的配置
            settings = settings ?? new JsonSerializerSettings
            {
                // 美化输出的 JSON 字符串
                Formatting = Formatting.Indented,
            };

            return JsonConvert.SerializeObject(obj, settings);
        }

        /// <summary>
        /// 序列化
        /// </summary>
        /// <param name="obj"></param>
        /// <returns></returns>
        public static string SerializeObject(this object obj)
        {
            // 设置 Json 序列化的配置
            var settings = new JsonSerializerSettings
            {
                // 美化输出的 JSON 字符串
                Formatting = Formatting.Indented,
            };

            return JsonConvert.SerializeObject(obj, settings);//GenerateClass
        }


        #region 深度克隆对象

        /// <summary>
        /// 深度克隆对象
        /// </summary>
        /// <typeparam name="T">对象的类型</typeparam>
        /// <param name="classObject">要克隆的对象</param>
        /// <returns>克隆后的对象</returns>
        public static T CloneObj<T>(this T classObject) where T : class
        {
            // 如果对象为 null，则返回 null
            if (classObject == null) return null;

            // 设置 Json 序列化的配置
            var settings = new JsonSerializerSettings
            {
                // 处理类型名称，确保在反序列化时可以创建正确的类型
                TypeNameHandling = TypeNameHandling.Auto,
                // 保留对象引用，防止对象重复
                PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                // 处理循环引用，避免无限递归
                ReferenceLoopHandling = ReferenceLoopHandling.Serialize,
                // 使用自定义的 ContractResolver 来处理私有字段和非公共类型
                ContractResolver = new PrivateResolver(),
                // 美化输出的 JSON 字符串
                // Formatting = Formatting.Indented,
                // 确保反序列化时完全替换现有对象
                ObjectCreationHandling = ObjectCreationHandling.Replace
            };

            // 将对象序列化为 JSON 字符串
            string jsonString = SerializeObject(classObject, settings);
            // 从 JSON 字符串反序列化回对象
            return DeserializeObject<T>(jsonString, settings);
        }

        /// <summary>
        /// 自定义的 ContractResolver，用于处理私有字段和非公共类型的序列化和反序列化
        /// </summary>
        public class PrivateResolver : DefaultContractResolver
        {
            /// <summary>
            /// 创建属性的自定义设置，确保所有属性都是可读写的
            /// </summary>
            /// <param name="member">成员信息</param>
            /// <param name="memberSerialization">成员序列化信息</param>
            /// <returns>配置好的 JSON 属性</returns>
            protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
            {
                // 调用基类方法创建属性
                var prop = base.CreateProperty(member, memberSerialization);
                // 确保属性是可读写的
                prop.Writable = true;
                prop.Readable = true;
                return prop;
            }

            /// <summary>
            /// 获取可序列化的成员，包括私有字段和属性
            /// </summary>
            /// <param name="objectType">对象类型</param>
            /// <returns>可序列化的成员列表</returns>
            protected override List<MemberInfo> GetSerializableMembers(Type objectType)
            {
                // 设置绑定标志，获取公共和非公共的实例字段和属性
                var flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance;
                // 获取所有字段和属性，并将它们转换为 MemberInfo 列表
                var members = objectType.GetFields(flags).Cast<MemberInfo>().Concat(objectType.GetProperties(flags)).ToList();
                return members;
            }
        }

        #endregion 深度克隆对象


        #region 生成实体类

        /// <summary>
        /// 根据JSON字符串生成实体类
        /// </summary>
        /// <param name="jsonContent">JSON字符串内容</param>
        /// <returns>生成的实体类的C#代码</returns>
        public static string GenerateEntitiesFromJson(string jsonContent)
        {
            JToken jsonObj = JToken.Parse(jsonContent);

            StringBuilder codeBuilder = new StringBuilder();
            codeBuilder.AppendLine("using System;");
            codeBuilder.AppendLine("using System.Collections.Generic;");
            codeBuilder.AppendLine();

            if (jsonObj.Type == JTokenType.Array)
            {
                GenerateClassCode(jsonObj.First, "RootElement", codeBuilder, new HashSet<string>());
            }
            else
            {
                GenerateClassCode(jsonObj, "RootElement", codeBuilder, new HashSet<string>());
            }

            return codeBuilder.ToString();
        }

        /// <summary>
        /// 递归生成每个JSON对象对应的类代码
        /// </summary>
        /// <param name="jToken">JSON对象</param>
        /// <param name="className">类名</param>
        /// <param name="codeBuilder">用于构建代码的StringBuilder</param>
        /// <param name="generatedClasses">已生成的类名集合，用于避免重复生成类</param>
        private static void GenerateClassCode(JToken jToken, string className, StringBuilder codeBuilder, HashSet<string> generatedClasses)
        {
            className = NormalizeClassName(className);

            if (!generatedClasses.Contains(className))
            {
                generatedClasses.Add(className);

                codeBuilder.AppendLine($"/// <summary>");
                codeBuilder.AppendLine($"/// Represents the {className} class.");
                codeBuilder.AppendLine($"/// </summary>");
                codeBuilder.AppendLine($"public class {className}");
                codeBuilder.AppendLine("{");

                if (jToken.Type == JTokenType.Object)
                {
                    foreach (var property in (JObject)jToken)
                    {
                        string propertyName = NormalizePropertyName(property.Key);
                        string propertyType = DeterminePropertyType(property.Value, property.Key, out bool isComplexType);

                        if (isComplexType)
                        {
                            GenerateClassCode(property.Value, property.Key, codeBuilder, generatedClasses);
                        }

                        codeBuilder.AppendLine($"    /// <summary>");
                        codeBuilder.AppendLine($"    /// Gets or sets the {property.Key} property.");
                        codeBuilder.AppendLine($"    /// </summary>");
                        codeBuilder.AppendLine($"    public {propertyType} {propertyName} {{ get; set; }}");
                    }
                }

                codeBuilder.AppendLine("}");
                codeBuilder.AppendLine();
            }
        }

        /// <summary>
        /// 确定属性的C#数据类型
        /// </summary>
        /// <param name="token">JSON token</param>
        /// <param name="propertyName">属性名称</param>
        /// <param name="isComplexType">是否为复杂类型</param>
        /// <returns>属性的C#数据类型</returns>
        private static string DeterminePropertyType(JToken token, string propertyName, out bool isComplexType)
        {
            isComplexType = false;

            switch (token.Type)
            {
                case JTokenType.Integer:
                    return token.Value<long>() > int.MaxValue || token.Value<long>() < int.MinValue ? "long" : "int";
                case JTokenType.Float:
                    return "double";
                case JTokenType.Boolean:
                    return "bool";
                case JTokenType.Date:
                    return "DateTime";
                case JTokenType.String:
                    return "string";
                case JTokenType.Array:
                    isComplexType = true;
                    var arrayType = DeterminePropertyType(token.First, propertyName, out bool _);
                    return $"List<{arrayType}>";
                case JTokenType.Object:
                    isComplexType = true;
                    return NormalizeClassName(propertyName);
                default:
                    return "string";
            }
        }

        /// <summary>
        /// 规范化类名（将名称转换为Pascal命名法）
        /// </summary>
        /// <param name="name">名称</param>
        /// <returns>规范化后的类名</returns>
        private static string NormalizeClassName(string name)
        {
            return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(name.Replace("_", " ").Replace("-", " ")).Replace(" ", "");
        }

        /// <summary>
        /// 规范化属性名（将名称转换为Pascal命名法）
        /// </summary>
        /// <param name="name">名称</param>
        /// <returns>规范化后的属性名</returns>
        private static string NormalizePropertyName(string name)
        {
            return CultureInfo.CurrentCulture.TextInfo.ToTitleCase(name.Replace("_", " ").Replace("-", " ")).Replace(" ", "");
        }

        #endregion 生成实体类

    }

}
